package com.rockcent.mall.lib.helper;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSSClient;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.rockcent.common.utils.HttpClientUtils;
import com.rockcent.mall.lib.domain.MiniAppConfig;
import com.rockcent.mall.lib.domain.UploadImageFile;
import com.rockcent.mall.lib.domain.enumclass.UploadFileBusinessType;
import com.rockcent.mall.lib.dto.QrCodeDto;
import com.rockcent.mall.lib.dto.UploadImageFileDto;
import com.rockcent.mall.lib.repository.MiniAppConfigRepository;
import com.rockcent.mall.lib.repository.UploadImageFileRepository;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by DK on 16/10/19.
 * 生成二维码帮助类
 */
@Component
public class QRCodeHelper {
    @Autowired
    private OSSClient ossClient;
    @Autowired
    private UploadImageFileRepository uploadImageFileRepository;
    @Autowired
    private MiniAppConfigRepository miniAppConfigRepository;
    private final Logger log = LoggerFactory.getLogger(QRCodeHelper.class);

    //生成二维码上传阿里云
    public UploadImageFileDto createQRCode(QrCodeDto qrCodeDto, String url, String pathName, UploadFileBusinessType uploadFileBusinessType, String env, String aliyunOssBucketName, String domainUploadsHttp) throws WriterException, IOException {
        // 生成二维码
        MultiFormatWriter writer = new MultiFormatWriter();
        BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 400, 400);
        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", os);
        InputStream byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
        log.info("======================>inputStream{}", byteArrayInputStream);
        return uploadImageFile(qrCodeDto, url, pathName, uploadFileBusinessType, env, aliyunOssBucketName, domainUploadsHttp, byteArrayInputStream);
    }


    private UploadImageFileDto uploadImageFile(QrCodeDto qrCodeDto, String url, String pathName, UploadFileBusinessType uploadFileBusinessType, String env, String aliyunOssBucketName, String domainUploadsHttp, InputStream byteArrayInputStream) {
        UploadImageFile uploadImageFile = new UploadImageFile();
        // 文件名
        String fileName = uploadImageFile.genFileName(pathName);
        String allPath = uploadImageFile.genAllPath(env, uploadFileBusinessType, fileName);

        uploadImageFile.setFileName(fileName);
        uploadImageFile.setPath("/" + allPath);
        uploadImageFile.setBusinessType(uploadFileBusinessType);
        uploadImageFile.setUserInfoId(qrCodeDto.getId());
        uploadImageFile.setMerchantId(qrCodeDto.getMerchantId());
        uploadImageFile.setMallId(qrCodeDto.getMallId());
        uploadImageFile = uploadImageFileRepository.save(uploadImageFile);
        // 重新生成的时候需要把产品的推广二维码重新设值
        /*product.setPromoteUrl(prop.domainUploadsHttp + uploadImageFile.getPath());
        merchantProductRepository.save(product);*/

        // 上传二维码到 oss
        ossClient.putObject(aliyunOssBucketName, allPath, byteArrayInputStream);

        UploadImageFileDto uploadImageFileDto = new UploadImageFileDto();
        uploadImageFileDto.setPath(domainUploadsHttp + uploadImageFile.getPath());
        uploadImageFileDto.setId(uploadImageFile.getId());
        uploadImageFileDto.setPromoteUrl(url);
        return uploadImageFileDto;
    }

    //生成base64位二维码
    public String createBase64QRCode(String url) throws WriterException, IOException {
        MultiFormatWriter writer = new MultiFormatWriter();
        BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 400, 400);
        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", Base64.getEncoder().wrap(os));
        return os.toString();
    }

    /**
     * 小程序二维码
     *
     * @param channelId
     * @param qrCodeDto
     * @param url
     * @param pathName
     * @param uploadFileBusinessType
     * @param env
     * @param aliyunOssBucketName
     * @param domainUploadsHttp
     * @return
     * @throws IOException
     */
    public UploadImageFileDto updateQRCode(Long channelId, QrCodeDto qrCodeDto, String url, String pathName, UploadFileBusinessType uploadFileBusinessType, String env, String aliyunOssBucketName, String domainUploadsHttp, MiniAppConfig miniAppConfig) throws IOException {

        String cgiBinUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + miniAppConfig.getAppId() + "&secret=" + miniAppConfig.getAppSecret();
        String result = HttpClientUtils.SINGLETON.sendGet(cgiBinUrl);
        Map mapTypes = JSON.parseObject(result);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String access_token = (String) mapTypes.get("access_token");
        log.info("======================>access_token{}", access_token);
        String qrCodeUrl = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=" + access_token;
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        InputStream byteArrayInputStream = null;
        try {
            HttpPost httpPost = new HttpPost(qrCodeUrl);

//        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
//        nvps.add(new BasicNameValuePair("path", "pages/product/list/list?channelId="+channelId));
//        nvps.add(new BasicNameValuePair("width", "1000"));
//        httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            String json = "{\"path\":\"pages/product/list/list?channelId=" + channelId + "\",\"width\":1000}";
            log.info("======================>==>json{}", json);
            StringEntity entity = new StringEntity(json);
            httpPost.setEntity(entity);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            response = httpclient.execute(httpPost);
            inputStream = response.getEntity().getContent();
//            InputStream is = entity.getContent();
//            String filePath = System.currentTimeMillis() + ".jpeg";
//            OutputStream fos = new FileOutputStream(new File(inputStream));
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            int ch;
            while ((ch = inputStream.read()) != -1) {
                swapStream.write(ch);
            }
            byteArrayInputStream = new ByteArrayInputStream(swapStream.toByteArray());
            log.info("======================>==>inputStream{}", byteArrayInputStream);
        } finally {
            if (null != httpclient) {
                httpclient.close();
            }
            if (null != response) {
                response.close();
            }
            if (null != byteArrayInputStream) {
                byteArrayInputStream.close();
            }
            if (null != response) {
                response.close();
            }
        }

        return uploadImageFile(qrCodeDto, url, pathName, uploadFileBusinessType, env, aliyunOssBucketName, domainUploadsHttp, byteArrayInputStream);

    }


    /**
     * 小程序二维码base64
     *
     * @param urls
     * @return
     * @throws IOException
     */
    public String createBase64QRCodeWxapp(String urls) throws IOException {

        URL url = new URL(urls);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        InputStream is = null;
        try {
            is = url.openStream();
            byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
            int n;

            while ((n = is.read(byteChunk)) > 0) {
                baos.write(byteChunk, 0, n);
            }
        } catch (IOException e) {
            log.warn("======================>Failed while reading bytes from {}: {}", url.toExternalForm(), e.getMessage());
            log.error(e.getMessage(),e);
            // Perform any other exception handling that's appropriate.
        } finally {
            if (is != null) {
                is.close();
            }
        }
        return new BASE64Encoder().encode(baos.toByteArray());
    }

    //生成base64位二维码
    public String createPaymentBase64QRCode(String url, int width, int height) throws WriterException, IOException {
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.MARGIN, new Integer(3));
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        MultiFormatWriter writer = new MultiFormatWriter();
        BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, width, height, hints);
        MatrixToImageConfig config = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, config);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", Base64.getEncoder().wrap(os));
        return os.toString();
    }

    /**
     * 爆款小程序二维码
     *
     * @param promotionCodeId
     * @param qrCodeDto
     * @param url
     * @param pathName
     * @param uploadFileBusinessType
     * @param env
     * @param aliyunOssBucketName
     * @param domainUploadsHttp
     * @return
     * @throws IOException
     */
    public UploadImageFileDto showQRCode(Long promotionCodeId, QrCodeDto qrCodeDto, String url, String pathName, UploadFileBusinessType uploadFileBusinessType, String env, String aliyunOssBucketName, String domainUploadsHttp) throws IOException {
        if (qrCodeDto == null || qrCodeDto.getMallId() == null) {
            return null;
        }
        MiniAppConfig miniAppConfig = miniAppConfigRepository.findByMallId(qrCodeDto.getMallId());
        if (miniAppConfig == null) {
            return null;
        }
        String result = HttpClientUtils.SINGLETON.sendGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + miniAppConfig.getAppId() + "&secret=" + miniAppConfig.getAppSecret());
        Map mapTypes = JSON.parseObject(result);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String access_token = (String) mapTypes.get("access_token");
        log.info("======================>access_token{}", access_token);
        String qrCodeUrl = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=" + access_token;
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        InputStream byteArrayInputStream = null;
        try {
            HttpPost httpPost = new HttpPost(qrCodeUrl);
            String json = "{\"path\":\"pages/product/list/list?promotionCodeId=" + promotionCodeId + "\",\"width\":1000}";
            log.info("======================>==>json{}", json);
            StringEntity entity = new StringEntity(json);
            httpPost.setEntity(entity);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            response = httpclient.execute(httpPost);
            inputStream = response.getEntity().getContent();
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            int ch;
            while ((ch = inputStream.read()) != -1) {
                swapStream.write(ch);
            }
            byteArrayInputStream = new ByteArrayInputStream(swapStream.toByteArray());
            log.info("======================>==>inputStream{}", byteArrayInputStream);
        } finally {
            if (null != httpclient) {
                httpclient.close();
            }
            if (null != response) {
                response.close();
            }
            if (null != byteArrayInputStream) {
                byteArrayInputStream.close();
            }
            if (null != response) {
                response.close();
            }
        }
        return uploadImageFile(qrCodeDto, url, pathName, uploadFileBusinessType, env, aliyunOssBucketName, domainUploadsHttp, byteArrayInputStream);

    }

    /**
     * 小程序码
     *
     * @param channelId
     * @param qrCodeDto
     * @param url
     * @param pathName
     * @param uploadFileBusinessType
     * @param env
     * @param aliyunOssBucketName
     * @param domainUploadsHttp
     * @return
     * @throws IOException
     */
    public UploadImageFileDto updateQRCodeForSmallProgram(Long channelId, QrCodeDto qrCodeDto, String url, String pathName, UploadFileBusinessType uploadFileBusinessType, String env, String aliyunOssBucketName, String domainUploadsHttp, MiniAppConfig miniAppConfig) throws IOException {

        String cgiBinUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + miniAppConfig.getAppId() + "&secret=" + miniAppConfig.getAppSecret();
        String result = HttpClientUtils.SINGLETON.sendGet(cgiBinUrl);
        Map mapTypes = JSON.parseObject(result);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String access_token = (String) mapTypes.get("access_token");
        log.info("======================>access_token{}", access_token);
        String qrCodeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token;
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        InputStream byteArrayInputStream = null;

        try {
            HttpPost httpPost = new HttpPost(qrCodeUrl);

//            String json = "{\"path\":\"pages/product/list/list?channelId=" + channelId + "\",\"width\":1000}";
            String json = "{" +
                    "\"scene\":\"" + channelId + "\"," +
                    "\"width\":1000," +
                    "\"auto_color\":true," +
                    "\"line_color\":{\"r\":\"0\",\"g\":\"0\",\"b\":\"0\"}" +
                    "}";
            log.info("======================>==>Json{}", json);
            StringEntity entity = new StringEntity(json);
            httpPost.setEntity(entity);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            response = httpclient.execute(httpPost);
            inputStream = response.getEntity().getContent();

            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            int ch;
            while ((ch = inputStream.read()) != -1) {
                swapStream.write(ch);
            }
            byteArrayInputStream = new ByteArrayInputStream(swapStream.toByteArray());
            log.info("======================>==>inputStream{}", byteArrayInputStream);
        } finally {
            if (null != httpclient) {
                httpclient.close();
            }
            if (null != response) {
                response.close();
            }
            if (null != byteArrayInputStream) {
                byteArrayInputStream.close();
            }
            if (null != response) {
                response.close();
            }
        }

        return uploadImageFile(qrCodeDto, url, pathName, uploadFileBusinessType, env, aliyunOssBucketName, domainUploadsHttp, byteArrayInputStream);

    }

}


